﻿using System;
using System.Text;
using Quantum.Core;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;

namespace Quantum.RabbitMq
{
    public class Subscriber : RabbitMqConnetion, ISubscribeBehavior
    {
        public void Subscribe(Action<string> messageHandler)
        {
            ConsumeMessage(o => Encoding.UTF8.GetString(o), messageHandler);
        }

        public void Subscribe<TIn>(Action<Incoming<TIn>> messageHandler)
        {
            ConsumeMessage(o =>
            {
                var json = Encoding.UTF8.GetString(o);
                return JsonFormatter.DeserializeJsonToObject<Incoming<TIn>>(json);
            },
            messageHandler);
        }

        private void ConsumeMessage<T>(Func<byte[], T> bytesHandler, Action<T> messageHandler)
        {
            using (var channel = Connection.CreateModel())
            {
                channel.ExchangeDeclare(exchange: "broadcast", type: "fanout");

                var queueName = channel.QueueDeclare().QueueName;
                channel.QueueBind(queue: queueName,
                    exchange: "broadcast",
                    routingKey: "");

                Console.WriteLine(" [*] Waiting for broadcast...");

                var consumer = new EventingBasicConsumer(channel);
                consumer.Received += (model, ea) =>
                {
                    var body = ea.Body;
                    var message = bytesHandler(body);
                    Console.WriteLine(" [x] {0}", message);
                    messageHandler(message);
                };

                channel.BasicConsume(queue: queueName,
                    autoAck: true,
                    consumer: consumer);
                Console.WriteLine(" Press [enter] to exit.");
            }
        }
    }
}
